//
// Created by Yun on 2025/2/19.
//

#include "bsp_uart.h"

/* 串口设备池 */
#define MAX_UART_NUM 5
Uart_Hw_Cfg_TypeDef* stUartHwCfgPool[MAX_UART_NUM] = {NULL};
uint8_t u8UartNum = 0;

uint8_t Bsp_Uart_Init(const void* pUartHwCfg,
                      uint8_t* u8RxBuffer,
                      uint16_t u16RxBufferSize,
                      uint8_t* u8TxBuffer,
                      uint16_t u16TxBufferSize,
                      pfNVIC_Callback_TypeDef pfRxFinishedCallback,
                      pfNVIC_Callback_TypeDef pfTxFinishedCallback,
                      uint8_t uint16Timeout)
{
    /* 参数检查 */
    if(pUartHwCfg == NULL ||
    u8UartNum >= MAX_UART_NUM ||
    u8RxBuffer == NULL || u16RxBufferSize == 0 ||
    u8TxBuffer == NULL || u16TxBufferSize == 0 ||
    pfRxFinishedCallback == NULL ||
    pfTxFinishedCallback == NULL) return BSP_ERROR;
    Uart_Hw_Cfg_TypeDef *pstHwCfg = (Uart_Hw_Cfg_TypeDef*)pUartHwCfg;

    /* 使能串口时钟 */
    if     (pstHwCfg->stHUart.Instance == USART1)
    {
        __HAL_RCC_USART1_CLK_ENABLE();
        HAL_NVIC_SetPriority(USART1_IRQn, pstHwCfg->u8ITPriority, 0);  // 设置优先级（根据系统调整）
        HAL_NVIC_EnableIRQ(USART1_IRQn);          // 使能UART全局中断
    }
    else if(pstHwCfg->stHUart.Instance == USART2)
    {
        __HAL_RCC_USART2_CLK_ENABLE();
        HAL_NVIC_SetPriority(USART2_IRQn, pstHwCfg->u8ITPriority, pstHwCfg->u8ITSubPriority);  // 设置优先级（根据系统调整）
        HAL_NVIC_EnableIRQ(USART2_IRQn);          // 使能UART全局中断
    }
    else if(pstHwCfg->stHUart.Instance == USART3)
    {
        __HAL_RCC_USART3_CLK_ENABLE();
        HAL_NVIC_SetPriority(USART3_IRQn, pstHwCfg->u8ITPriority, pstHwCfg->u8ITSubPriority);  // 设置优先级（根据系统调整）
        HAL_NVIC_EnableIRQ(USART3_IRQn);          // 使能UART全局中断
    }
    else if(pstHwCfg->stHUart.Instance == UART4)
    {
        __HAL_RCC_UART4_CLK_ENABLE();
        HAL_NVIC_SetPriority(UART4_IRQn, pstHwCfg->u8ITPriority, pstHwCfg->u8ITSubPriority);  // 设置优先级（根据系统调整）
        HAL_NVIC_EnableIRQ(UART4_IRQn);          // 使能UART全局中断
    }
    else if(pstHwCfg->stHUart.Instance == UART5)
    {
        __HAL_RCC_UART5_CLK_ENABLE();
        HAL_NVIC_SetPriority(UART5_IRQn, pstHwCfg->u8ITPriority, pstHwCfg->u8ITSubPriority);  // 设置优先级（根据系统调整）
        HAL_NVIC_EnableIRQ(UART5_IRQn);          // 使能UART全局中断
    }
    else return BSP_ERROR;

    /* 初始化GPIO */
    if(Bsp_Gpio_Init(&pstHwCfg->stTx) != BSP_OK) return BSP_ERROR;
    if(Bsp_Gpio_Init(&pstHwCfg->stRx) != BSP_OK) return BSP_ERROR;

    /* 初始化串口 */
    if(HAL_UART_Init(&pstHwCfg->stHUart) != HAL_OK) return BSP_ERROR;

    /* 中断 */
    __HAL_UART_DISABLE_IT(&pstHwCfg->stHUart, UART_IT_TXE);  // 禁用发送中断
    __HAL_UART_DISABLE_IT(&pstHwCfg->stHUart, UART_IT_IDLE);  // 禁用发送中断
    __HAL_UART_ENABLE_IT(&pstHwCfg->stHUart, UART_IT_RXNE);  // 使能接收中断

    pstHwCfg->stRxBuffer.u8Buffer = u8RxBuffer;
    pstHwCfg->stRxBuffer.u16BufferSize = u16RxBufferSize;
    pstHwCfg->stRxBuffer.u16Len = 0;
    pstHwCfg->stTxBuffer.u8Buffer = u8TxBuffer;
    pstHwCfg->stTxBuffer.u16BufferSize = u16TxBufferSize;
    pstHwCfg->stTxBuffer.u16Len = 0;
    pstHwCfg->u16Timeout = uint16Timeout;
    pstHwCfg->pfRxFinishedCallback = pfRxFinishedCallback;
    pstHwCfg->pfTxFinishedCallback = pfTxFinishedCallback;

    /* 缓冲区大小检查 */
    if(pstHwCfg->stRxBuffer.u16BufferSize == 0 || pstHwCfg->stTxBuffer.u16BufferSize == 0) return BSP_ERROR;

    /* 保存设备到设备池中 */
    stUartHwCfgPool[u8UartNum++] = pstHwCfg;

    return BSP_OK;
}

uint8_t Bsp_Uart_Transmit(const void* pUartHwCfg, uint8_t* pu8TxData, uint16_t u16Len)
{
    /* 参数检查 */
    if(pUartHwCfg == NULL || pu8TxData == NULL || u16Len == 0) return BSP_ERROR;
    Uart_Hw_Cfg_TypeDef *pstHwCfg = (Uart_Hw_Cfg_TypeDef*)pUartHwCfg;

    /* 清空发送缓冲区 */
    memset(pstHwCfg->stTxBuffer.u8Buffer, 0, pstHwCfg->stTxBuffer.u16Len);
    pstHwCfg->stTxBuffer.u16Len = 0;

    /* 写入数据 */
    memcpy(pstHwCfg->stTxBuffer.u8Buffer, pu8TxData, u16Len);
    pstHwCfg->stTxBuffer.u16Len = u16Len;
    pstHwCfg->u16Temp = 0;

    /* 开启发送中断 */
    __HAL_UART_ENABLE_IT(&pstHwCfg->stHUart, UART_IT_TXE);

    return BSP_OK;
}
uint8_t Bsp_Uart_Receive(const void* pUartHwCfg, uint8_t* pu8RxData, uint16_t* pu16Len)
{
    if(pUartHwCfg == NULL || pu8RxData == NULL || pu16Len == NULL) return BSP_ERROR;
    Uart_Hw_Cfg_TypeDef *pstHwCfg = (Uart_Hw_Cfg_TypeDef*)pUartHwCfg;

    /* 读取数据 */
    memcpy(pu8RxData, pstHwCfg->stRxBuffer.u8Buffer, pstHwCfg->stRxBuffer.u16Len);
    *pu16Len = pstHwCfg->stRxBuffer.u16Len;

    /* 清空接收缓冲区 */
    memset(pstHwCfg->stRxBuffer.u8Buffer, 0, pstHwCfg->stRxBuffer.u16Len);
    pstHwCfg->stRxBuffer.u16Len = 0;

    return BSP_OK;
}

uint8_t Bsp_Uart_SetBaudrate(const void* pUartHwCfg, uint32_t u32Baudrate)
{
    if(pUartHwCfg == NULL) return BSP_ERROR;
    Uart_Hw_Cfg_TypeDef *pstHwCfg = (Uart_Hw_Cfg_TypeDef*)pUartHwCfg;

    pstHwCfg->stHUart.Init.BaudRate = u32Baudrate;
    if(HAL_UART_Init(&pstHwCfg->stHUart) != HAL_OK) return BSP_ERROR;
    return BSP_OK;
}

/* -------------------- 串口中断处理函数  --------------------*/

/*!
 * @brief 串口中断通用处理函数
 * @param pstHwCfg 串口配置
 * @note 该函数处理串口中断，包括接收中断、空闲中断、发送中断
 */
static void Bsp_Uart_IRQHandler(Uart_Hw_Cfg_TypeDef *pstHwCfg)
{
    /* 参数检查 */
    if(pstHwCfg == NULL) return;
    /* 接收中断处理 */
    if(__HAL_UART_GET_FLAG(&pstHwCfg->stHUart, UART_FLAG_RXNE) &&
       __HAL_UART_GET_IT_SOURCE(&pstHwCfg->stHUart, UART_IT_RXNE)) {

        __HAL_UART_ENABLE_IT(&pstHwCfg->stHUart, UART_IT_IDLE);  // 使能空闲中断
        pstHwCfg->u16Retry = 0;

        /* 超缓存 */
        if(pstHwCfg->stRxBuffer.u16Len >= pstHwCfg->stRxBuffer.u16BufferSize) return;

        /* 读取数据到接收缓冲区 */
        pstHwCfg->stRxBuffer.u8Buffer[pstHwCfg->stRxBuffer.u16Len++] = (uint8_t) (pstHwCfg->stHUart.Instance->DR);
    }
    /* 空闲中断处理 */
    if(__HAL_UART_GET_FLAG(&pstHwCfg->stHUart, UART_FLAG_IDLE) &&
       __HAL_UART_GET_IT_SOURCE(&pstHwCfg->stHUart, UART_IT_IDLE))
    {
        if(pstHwCfg->u16Retry++ > pstHwCfg->u16Timeout) return;
        pstHwCfg->u16Retry = 0;

        /* 处理空闲中断 */
        __HAL_UART_CLEAR_FLAG(&pstHwCfg->stHUart, UART_FLAG_IDLE);
        __HAL_UART_DISABLE_IT(&pstHwCfg->stHUart, UART_IT_IDLE);

        /* 释放接收完成信号 */
        if (pstHwCfg->stRxBuffer.u16Len > 0)
        {
            pstHwCfg->pfRxFinishedCallback(pstHwCfg);
        }
    }
    /* 发送中断处理 */
    if(__HAL_UART_GET_FLAG(&pstHwCfg->stHUart, UART_FLAG_TXE) &&
       __HAL_UART_GET_IT_SOURCE(&pstHwCfg->stHUart, UART_IT_TXE)) {

        /* 发送数据 */
        pstHwCfg->stHUart.Instance->DR = (uint16_t) pstHwCfg->stTxBuffer.u8Buffer[pstHwCfg->u16Temp++];

        /* 发送完成 */
        if(pstHwCfg->stTxBuffer.u16Len == pstHwCfg->u16Temp)
        {
            // 发送完成信号
            pstHwCfg->pfTxFinishedCallback(pstHwCfg);
            __HAL_UART_DISABLE_IT(&pstHwCfg->stHUart, UART_IT_TXE);
        }
   }
}

/*!
 * @brief 找到串口配置
 * @param pUart 串口设备号
 * @return 串口配置
 * @note 该函数根据传入的串口设备号，在设备池中找到对应的串口配置
 */
static  Uart_Hw_Cfg_TypeDef* Bsp_Find_Uart_Hw_Cfg(USART_TypeDef* pUart)
{
    uint8_t u8Idx = 0;
    Uart_Hw_Cfg_TypeDef *pstHwCfg = NULL;

    /* 遍历设备池 */
    for (u8Idx = 0; u8Idx < u8UartNum; u8Idx++)
    {
        pstHwCfg = stUartHwCfgPool[u8Idx];
        if (pstHwCfg->stHUart.Instance == pUart) break;
    }
    return pstHwCfg;
}

#define UART_IRQ(UARTx_IRQ_FUNC, UARTx) \
void UARTx_IRQ_FUNC(void)               \
{                                       \
    Uart_Hw_Cfg_TypeDef *pstHwCfg = Bsp_Find_Uart_Hw_Cfg(UARTx);\
    Bsp_Uart_IRQHandler(pstHwCfg); \
}\

/* -------------------- 系统中断处理函数  --------------------*/
UART_IRQ(USART1_IRQHandler, USART1)
UART_IRQ(USART2_IRQHandler, USART2)
UART_IRQ(USART3_IRQHandler, USART3)
UART_IRQ(UART4_IRQHandler, UART4)
UART_IRQ(UART5_IRQHandler, UART5)

//void USART1_IRQHandler(void)
//{
//    // 找到串口配置
//    Uart_Hw_Cfg_TypeDef *pstHwCfg = Bsp_Find_Uart_Hw_Cfg(USART1);
//    // 处理中断
//    Bsp_Uart_IRQHandler(pstHwCfg);
//}


Uart_Slow_Interface_TypeDef stBspUartInterface = {
        .Init = Bsp_Uart_Init,
        .Transmit = Bsp_Uart_Transmit,
        .Receive = Bsp_Uart_Receive,
        .SetBaudrate = Bsp_Uart_SetBaudrate,
};
